﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Xml;

namespace DGen
{
    /// <summary>
    /// Static filehelpers class.
    /// </summary>
    public static class DFile
    {
        /*
         * A few useful file accessing methods.
         *      GetFileAsString(filename)
         *      writeStringToFile(filename,string);
         *      WriteToFile(filename,string[])
         */

        /// <summary>
        /// Get's entire contents as string.
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string GetFileAsString(string fileName)
        {
            try
            {
                using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    using (var sReader = new StreamReader(fileStream, Encoding.GetEncoding(1252)))
                    {
                        string contents = sReader.ReadToEnd();
                        return contents;
                    }
                }
            }
            catch (Exception ex)
            {
                return "Problem Reading File\t" + ex.Message;
            }
        }

        /// <summary>
        /// Get's entire contents of file as an array made up of each line of the file. 
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string[] GetFileAsArray(string fileName)
        {
            return Regex.Split(GetFileAsString(fileName), Environment.NewLine);
        }

        /// <summary>
        /// Write a single string to file. File must exist and will be overwritten.
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="input"></param>
        public static void WriteToFile(string fileName, string input)
        {
            StreamWriter sWriter = null;

            string contents = input;
            try
            {
                var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
                sWriter = new StreamWriter(fileStream);
                sWriter.Write(contents);
            }
            catch (Exception e)
            {
                Console.Write("Can't find that file, dumbass!\\n");
                Console.Write(e.Message);
            }


            finally
            {
                if (sWriter != null)
                {
                    sWriter.Close();
                }
            }
        }

        /// <summary>
        /// Overloaded version to append to existing or create file.
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="input"></param>
        /// <param name="AppendText"></param>
        public static void WriteToFile(string fileName, string input, bool AppendText)
        {
            StreamWriter sWriter = null;

            string contents = input;
            try
            {
                var fileStream = new FileStream(fileName, FileMode.Append, FileAccess.Write);
                sWriter = new StreamWriter(fileStream);
                sWriter.Write(contents);
            }
            catch (Exception e)
            {
                Console.Write("Can't find that file, dumbass!\\n");
                Console.Write(e.Message);
            }


            finally
            {
                if (sWriter != null)
                {
                    sWriter.Close();
                }
            }
        }

        /// <summary>
        /// Writes an array, line by line to file. File must exist and will be overwritten.
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="input"></param>
        public static void WriteToFile(string fileName, string[] input)
        {
            StreamWriter sWriter = null;
            try
            {
                var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Write);
                sWriter = new StreamWriter(fileStream);
                foreach (string strLine in input)
                {
                    sWriter.WriteLine(strLine);
                }
            }
            catch (Exception e)
            {
                Console.Write("Can't find that file, dumbass!\\n");
                Console.Write(e.Message);
            }
            finally
            {
                if (sWriter != null)
                {
                    sWriter.Close();
                }
            }
        }

        /// <summary>
        /// Get's Xml file as formatted text.
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string GetXmlFileAsString(string fileName)
        {
            var xmlDocument = new XmlDocument();
            xmlDocument.Load(fileName);
            var stringWriter = new StringWriter();
            var xmlTextWriter = new XmlTextWriter(stringWriter);
            xmlTextWriter.Formatting = Formatting.Indented;
            xmlDocument.WriteTo(xmlTextWriter);
            xmlTextWriter.Flush();
            return stringWriter.ToString();
        }

        /// <summary>
        /// append txt note to log. no options
        /// </summary>
        /// <param name="VarX"></param>
        public static void WriteToLog(string VarX)
        {
            string Var2 = DateTime.Today.ToShortDateString() + "\t" + VarX + Environment.NewLine;
            File.AppendAllText(@"CurrentLog.txt", Var2);
        }
        /// <summary>
        /// writes to log but does not use newline at end of entry.
        /// </summary>
        /// <param name="VarX"></param>
        /// <param name="suppressnewline"></param>
        public static void WriteToLog(string VarX, bool suppressnewline)
        {
            string Var2 = DateTime.Today.ToShortDateString() + "\t" + VarX;
            File.AppendAllText(@"CurrentLog.txt", Var2);
        }

        /// <summary>
        /// Returns a single line. May be slow with large files.
        /// </summary>
        /// <param name="fName"></param>
        /// <param name="lineNumber"></param>
        /// <returns></returns>
        public static string GetLineAt(string fName, int lineNumber)
        {
            string moo = File.ReadAllLines(fName)[lineNumber];
            return moo;
        }
        /// <summary>
        /// inserts line into a file at given position (line number)
        /// </summary>
        /// <param name="fName"></param>
        /// <param name="lineNumber"></param>
        /// <param name="lineX"></param>
        public static void PutLineAt (string fName, int lineNumber, string lineX)
        {
            string strTextFileName = fName;
            int iInsertAtLineNumber = lineNumber;
            string strTextToInsert = lineX;
            System.Collections.ArrayList lines = new System.Collections.ArrayList ();
            StreamReader rdr = new StreamReader (
                strTextFileName);
            string line;
            while ((line = rdr.ReadLine ()) != null)
            {
                lines.Add (line);
            }

            rdr.Close ();
            if (lines.Count > iInsertAtLineNumber)
            {
                lines.Insert (iInsertAtLineNumber,
                   strTextToInsert);
            }
            else
            {
                lines.Add (strTextToInsert);
            }
            StreamWriter wrtr = new StreamWriter(
                strTextFileName);
            foreach (string strNewLine in lines)
                wrtr.WriteLine(strNewLine);
            wrtr.Close();
        }

        /// <summary>
        /// Returns a unique file name AND path based on GUID. 
        /// Result will be of the form c:\windows\temp\31AFA461-04DF-416c-9F7F-FB54CDFBD540.tmp
        /// </summary>
        /// <returns></returns>
        public static string uniqueFileName()
        {
            Guid myGuid = Guid.NewGuid();
            string tPath = Path.GetTempPath();
            tPath = Path.Combine(tPath, myGuid.ToString() + ".tmp");
            return tPath;
        }
        /// <summary>
        ///over loaded version where extension doesn't thave to be .tmp
        /// </summary>
        /// <param name="extension"></param>
        /// <returns></returns>
        public static string uniqueFileName(string extension)
        {
            Guid myGuid = Guid.NewGuid();
            string tPath = Path.GetTempPath();
            tPath = Path.Combine(tPath, myGuid.ToString() + extension);
            return tPath;
        }
        /// <summary>
        /// Extension must be of the form ".txt". 
        /// </summary>
        /// <param name="extension"></param>
        /// <param name="fNameToSuffix">file name stub to put at end.</param>
        /// <param name="useTimeStamp"></param>
        /// <returns></returns>
        public static string uniqueFileName(string extension, string fNameToSuffix, bool useTimeStamp)
        {
            foreach (char c in Path.GetInvalidFileNameChars())
            {
                fNameToSuffix = DText.Left(fNameToSuffix.Replace(c, '_'), 8);
            }


            DateTime dt = DateTime.Now;

            string tmpDt = dt.ToString(@"yyyy\-MM\-dd\_HH\_mm\_ss\_");
            string tPath = Environment.CurrentDirectory;
            string tempFileName = tmpDt+fNameToSuffix+ extension;
             tPath = Path.Combine(tPath, tempFileName);
            
            return tPath;
        }

        /// <summary>
        /// Does what it says on the tin. Not optimised so will run like a dog.
        /// Uses the environmental newline.
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static long CountLinesInFile (string f)
        {
            long count = 0;
            using (StreamReader r = new StreamReader (f))
            {
                string line = "";
                while ((line = r.ReadLine ()) != null)
                {
                    if (line.Length > 0)
                    {
                        count++;
                    }
                }
            }
            return count;
        }
    }
}
